hvm: fix single stepping on debugger
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 11 Nov 2008 11:47:03 +0000 (11:47 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 11 Nov 2008 11:47:03 +0000 (11:47 +0000)
The debuggee domain will die with unexpected trap
on single stepping of emulated instruction.

Signed-off-by: Kouya Shimura <kouya@jp.fujitsu.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/vmx/realmode.c
xen/arch/x86/hvm/vmx/vmx.c

index c635f5204aeef649f9c4156565bf994a06edada6..499cd619d4a0b4c8848baa07bb7e77815308d407 100644 (file)
@@ -739,6 +739,23 @@ static void svm_inject_exception(
     struct vmcb_struct *vmcb = curr->arch.hvm_svm.vmcb;
     eventinj_t event = vmcb->eventinj;
 
+    switch ( trapnr )
+    {
+    case TRAP_debug:
+        if ( guest_cpu_user_regs()->eflags & X86_EFLAGS_TF )
+        {
+            __restore_debug_registers(curr);
+            vmcb->dr6 |= 0x4000;
+        }
+    case TRAP_int3:
+        if ( curr->domain->debugger_attached )
+        {
+            /* Debug/Int3: Trap to debugger. */
+            domain_pause_for_debugger();
+            return;
+        }
+    }
+
     if ( unlikely(event.fields.v) &&
          (event.fields.type == X86_EVENTTYPE_HW_EXCEPTION) )
     {
@@ -765,13 +782,6 @@ static void svm_inject_exception(
     {
         HVMTRACE_2D(INJ_EXC, trapnr, errcode);
     }
-
-    if ( (trapnr == TRAP_debug) &&
-         (guest_cpu_user_regs()->eflags & X86_EFLAGS_TF) )
-    {
-        __restore_debug_registers(curr);
-        vmcb->dr6 |= 0x4000;
-    }
 }
 
 static int svm_event_pending(struct vcpu *v)
index b067eb1615affe95ceb23a32653c688e840eb543..4af2848406ecf539c7998dd7eea38835c452f28d 100644 (file)
@@ -149,17 +149,25 @@ static void realmode_emulate_one(struct hvm_emulate_ctxt *hvmemul_ctxt)
             hvmemul_ctxt->exn_insn_len = 0;
         }
 
-        if ( curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE )
+        if ( unlikely(curr->domain->debugger_attached) &&
+             ((hvmemul_ctxt->exn_vector == TRAP_debug) ||
+              (hvmemul_ctxt->exn_vector == TRAP_int3)) )
+        {
+            domain_pause_for_debugger();
+        }
+        else if ( curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE )
         {
             gdprintk(XENLOG_ERR, "Exception %02x in protected mode.\n",
                      hvmemul_ctxt->exn_vector);
             goto fail;
         }
-
-        realmode_deliver_exception(
-            hvmemul_ctxt->exn_vector,
-            hvmemul_ctxt->exn_insn_len,
-            hvmemul_ctxt);
+        else
+        {
+            realmode_deliver_exception(
+                hvmemul_ctxt->exn_vector,
+                hvmemul_ctxt->exn_insn_len,
+                hvmemul_ctxt);
+        }
     }
 
     return;
index 801b6da347566e2816c10732ff70fd62ccd72a2f..4156f02ad1138e6a72b3e396f8285248301e1d2d 100644 (file)
@@ -1118,6 +1118,24 @@ static void __vmx_inject_exception(int trap, int type, int error_code)
 void vmx_inject_hw_exception(int trap, int error_code)
 {
     unsigned long intr_info = __vmread(VM_ENTRY_INTR_INFO);
+    struct vcpu *curr = current;
+
+    switch ( trap )
+    {
+    case TRAP_debug:
+        if ( guest_cpu_user_regs()->eflags & X86_EFLAGS_TF )
+        {
+            __restore_debug_registers(curr);
+            write_debugreg(6, read_debugreg(6) | 0x4000);
+        }
+    case TRAP_int3:
+        if ( curr->domain->debugger_attached )
+        {
+            /* Debug/Int3: Trap to debugger. */
+            domain_pause_for_debugger();
+            return;
+        }
+    }
 
     if ( unlikely(intr_info & INTR_INFO_VALID_MASK) &&
          (((intr_info >> 8) & 7) == X86_EVENTTYPE_HW_EXCEPTION) )
@@ -1134,13 +1152,6 @@ void vmx_inject_hw_exception(int trap, int error_code)
                          TRC_PAR_LONG(current->arch.hvm_vcpu.guest_cr[2]));
     else
         HVMTRACE_2D(INJ_EXC, trap, error_code);
-
-    if ( (trap == TRAP_debug) &&
-         (guest_cpu_user_regs()->eflags & X86_EFLAGS_TF) )
-    {
-        __restore_debug_registers(current);
-        write_debugreg(6, read_debugreg(6) | 0x4000);
-    }
 }
 
 void vmx_inject_extint(int trap)